package chan2client

import (
	"fmt"
	"sync"

	"starsine.cn/appTpl/cmn/logs"
	"starsine.cn/appTpl/svclog/src/fe/clientinfo"
	"starsine.cn/appTpl/svclog/src/fe/ws-server/wsserver"
)

type Ws2ClientMap struct {
	c2s map[*wsserver.WsServer]*clientinfo.ClientInfo
	s2c map[*clientinfo.ClientInfo]*wsserver.WsServer
	sync.RWMutex
}

func CreateWs2ClientMap() *Ws2ClientMap {
	p := new(Ws2ClientMap)

	p.c2s = make(map[*wsserver.WsServer]*clientinfo.ClientInfo)
	p.s2c = make(map[*clientinfo.ClientInfo]*wsserver.WsServer)

	return p
}

func (p *Ws2ClientMap) AddWsClient(c *wsserver.WsServer, s *clientinfo.ClientInfo) {
	p.RWMutex.Lock()
	defer p.RWMutex.Unlock()

	p.c2s[c] = s
	p.s2c[s] = c
}

func (p *Ws2ClientMap) DelWsClient(s *clientinfo.ClientInfo) {
	p.RWMutex.Lock()
	defer p.RWMutex.Unlock()

	c, ok := p.s2c[s]
	if !ok {
		logs.Errorf("wshandler.Ws2ClientMap inner error")
		panic(fmt.Sprintf("wshandler.Ws2ClientMap inner error occur, c=%p, s=%p", c, s))
	}
	delete(p.c2s, c)
	delete(p.s2c, s)
}

func (p *Ws2ClientMap) DelWsConn(c *wsserver.WsServer) {
	p.RWMutex.Lock()
	defer p.RWMutex.Unlock()

	s, ok := p.c2s[c]
	if !ok {
		logs.Errorf("wshandler.Ws2ClientMap inner error")
		panic(fmt.Sprintf("wshandler.Ws2ClientMap inner error occur, c=%p, s=%p", c, s))
	}
	delete(p.c2s, c)
	delete(p.s2c, s)
}

func (p *Ws2ClientMap) GetUserFromWsConn(c *wsserver.WsServer) (*clientinfo.ClientInfo, bool) {
	p.RWMutex.RLock()
	defer p.RWMutex.RUnlock()

	svc, ok := p.c2s[c]

	return svc, ok
}

func (p *Ws2ClientMap) ForEach(f func(*wsserver.WsServer, *clientinfo.ClientInfo) bool) {
	p.RWMutex.RLock()
	defer p.RWMutex.RUnlock()

	for c, s := range p.c2s {
		if !f(c, s) {
			break
		}
	}
}

func (p *Ws2ClientMap) Dump() (str string) {
	p.RWMutex.RLock()
	defer p.RWMutex.RUnlock()

	str += fmt.Sprintln("Ws2ClientMap:")
	for c, s := range p.c2s {
		str += fmt.Sprintln("----------------------------")
		str += fmt.Sprintln("key: ", c)
		str += fmt.Sprintln(s)
	}

	return str
}
